package com.licq.ldoc.parser.impl;

import java.util.HashMap;
import java.util.Map;

import com.licq.ldoc.domain.Element;
import com.licq.ldoc.parser.Parser;

/**
 * 
 * @author liujian
 *
 * @param <T>
 */
public abstract class AbstractParser<T> implements Parser<T> {
	
	/**
	 * guarantee multi-thread safety
	 */
	private static ThreadLocal<Status> StatusTracker = new ThreadLocal<Status>();
	
	public static Status getCurrentStatus() {
		if (StatusTracker.get() == null) {
			synchronized (StatusTracker) {
				if (StatusTracker.get() == null) {
					StatusTracker.set(new Status());
				}
			}
		}
		return StatusTracker.get();
	}
	
	protected void resetCurrentStatus() {
		StatusTracker.set(null);
	}
	
	protected int getCurrentLevel() {
		return getCurrentStatus().getLevel();
	}
	
	protected void forwardCurrentLevel() {
		getCurrentStatus().setLevel(getCurrentLevel() + 1);
	}
	
	protected void backwardCurrentLevel() {
		getCurrentStatus().setLevel(getCurrentLevel() - 1);
	}
	
	protected void recordClazzToHandled(Class<?> clazz, Element element) {
		getCurrentStatus().addHandled(clazz, element);
	}
	
	protected boolean isClazzHandled(Class<?> clazz) {
		return getCurrentStatus().hasHandled(clazz);
	}
	
	protected Element getExistsElement(Class<?> clazz) {
		return getCurrentStatus().getHandled(clazz);
	}

	public static class Status {
		private int level = 0;
		
		private Map<Class<?>, Element> alreadyHandles = new HashMap<Class<?>, Element>();
		
		/** 特殊需求需要区分顶级类 */
		private Class<?> topClazz;

		public int getLevel() {
			return level;
		}

		public void setLevel(int level) {
			this.level = level;
		}
		
		public void addHandled(Class<?> clazz, Element element) {
			alreadyHandles.put(clazz, element);
		}
		
		public boolean hasHandled(final Class<?> clazz) {
			return getHandled(clazz) != null;
		}
		
		@SuppressWarnings("unchecked")
		public Element getHandled(Class<?> clazz) {
			return alreadyHandles.get(clazz);
		}

		public Class<?> getTopClazz() {
			return topClazz;
		}

		public void setTopClazz(Class<?> topClazz) {
			this.topClazz = topClazz;
		}

	}

}